#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <map>
#include <string>

#include "GPSdata.hpp"
#include "GPSsplitter.hpp"

using namespace ModuleData;

GPSdata::GPSdata( ObjGen g_func, ObjDel d_func )
  :obj_creator( g_func ),
   obj_releaser( d_func ),
   sentence_type( GPS_SENTENCE_VOID ),
   data_info(),
   is_initialized( false ),
   is_activated( false )
{
  bzero( orig_data, PACKAGE_SIZE );
}

void GPSdata::init_data( char* _orig, GPSsplitter& _paser ) throw(GPSdata_error)
{
  // 实际上需要重新清理完所有字段再进行分析
  sentence_type = GPS_SENTENCE_VOID;
  for (std::map< int, void* >::iterator i=data_info.begin(); i != data_info.end(); ++i)
    {
      obj_releaser( i->first, i->second );
    }
  data_info.clear();
  is_initialized = false;
  is_activated = false;
  bzero( orig_data, PACKAGE_SIZE );

  // 拷贝缓冲中的串到orig_data中，再进行检查
  int copy_bytes = strlen( _orig );

  if ( copy_bytes >= PACKAGE_SIZE )
    {
      throw GPSdata_error( GPSdata_error::INIT_DATA_ORIG_TOO_LONG, _orig );
    }

  strncpy( orig_data, _orig, PACKAGE_SIZE );

  // 调用解析器填写字段
  if ( _paser( orig_data, this ) )
    {
      is_initialized = true;
    }
  else
    {
      throw GPSdata_error( GPSdata_error::INIT_DATA_PASER_FAIL, _orig );
    }

}

void* GPSdata::get_value( int attribute_id ) const
{
  std::map<int, void*>::const_iterator i;
  i = data_info.find( attribute_id );
  if ( i != data_info.end() )
    {
      return i->second;
    }
  else
    {
      return NULL;
    }
}

void GPSdata::set_value( int attribute_id, const char *value )
{
  data_info[ attribute_id ] = obj_creator( attribute_id, value );
}

GPSdata_error::GPSdata_error( int _id, void *_info )
  : error_id( _id ), info( _info )
{
  if( _id < 0 || _id >= ERROR_MAX )
    {
      error_id = ERROR_MAX;
    }
}

const char* GPSdata_error::error_info[ ERROR_MAX+1 ] = 
  {
    "init_data: argument _orig's length is longer than buffer\n",
    "init_data: parser return a false value\n",
    "the error_id is an invalid id\n"
  };

static void* default_generator( int attr_id, const char* info )
{
  std::string *p = new std::string( info );

  return reinterpret_cast<void*>( p );
}

ObjGen ModuleData::default_gen = default_generator;

static void default_deconstructor( int attr_id, void* address )
{
  std::string *p = static_cast<std::string*>( address );
  delete p;
}

ObjDel ModuleData::default_del = default_deconstructor;
